;
;  Program:  LD
;  Author:  Richard Conn
;  Version:  1.1
;  Date:  6 Jan 83
;  Previous Versions:  1.0 (6 Dec 82)
;
;	LD Loads the named Directory file (LD=Load Directory) NAMES.DIR or
; that file specified in the command line into the memory-resident directory
; buffer.  It also has the capability of displaying the contents of this
; buffer to the user.  Forms of this command are:
;
;		LD		<-- Display Loaded Directory
;		LD filename	<-- Load Directory filename.DIR
;		LD filename.typ	<-- Load Directory filename.typ
;		LD //		<-- Ask for Help
;
vers	equ	11

;
;	This program is Copyright (c) 1982, 1983 by Richard Conn
;	All Rights Reserved
;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;	The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;


;
;  Constants
;
cr	equ	0dh
lf	equ	0ah
tfcb	equ	5ch	; ZCPR2 FCB

;
;  Externals
;
	ext	zgpins	; installation program
	ext	zfninit	; reinit NAMES.DIR
	ext	zdname	; load names into buffer
	ext	codend	; end of code
	ext	moveb	; move routine
	ext	print	; print routine
	ext	padc	; print A as decimal chars
	ext	cout	; output char
	ext	crlf	; new line
	ext	retud	; return current user/disk

;
;  Branch to Start of Program
;
	jmp	start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	0FFH	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	0FFH	; EXTERNAL PATH?
MCREQD:
	DB	000H	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	0FFH	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	000H	; CURRENT INDIC AND DMA?
NDREQD:
	DB	0FFH	; NAMED DIRECTORIES?
Z2CLASS:
	DB	0	; CLASS 0
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Start of Program
;
start:
	call	zgpins	; init ZCPR2 routines
	call	retud	; get current user number
	mov	a,b	; save current disk number away
	sta	cdisk
	mov	a,c	; save current user number away
	sta	cuser

	call	print
	db	'LD  Version '
	db	(vers/10)+'0','.',(vers mod 10)+'0',0

	lhld	ndradr	; check for facility support in the first place
	mov	a,h
	ora	l	; HL=0 if no facilities for mem-based named dirs
	jnz	start0
	call	print
	db	cr,lf,'Memory-Based Named Directories Not Supported'
	db	cr,lf,'on this System -- Aborting',0
	ret

start0:
	lxi	h,tfcb+1	; pt to first byte of file name
	mov	a,m	; get it
	cpi	' '	; display loaded directory if no file name given
	jz	ldisp
	cpi	'/'	; option?
	jnz	start1	; load directory if file specified

	call	print
	db	cr,lf,'	LD is the Load Directory program for ZCPR2.'
	db	cr,lf,'The functions of LD are to load the memory-resident'
	db	cr,lf,'named directory buffer from the specified or implied'
	db	cr,lf,'disk file and to display the contents of the named'
	db	cr,lf,'directory buffer.'
	db	cr,lf
	db	cr,lf,'	The forms of the LD command are --',cr,lf
	db	cr,lf,'		LD		<-- Display Loaded Directory'
	db	cr,lf,'		LD filename	<-- Load filename.DIR'
	db	cr,lf,'		LD filename.typ	<-- Load filename.typ'
	db	cr,lf,'		LD //		<-- Print this Help Message'
	db	cr,lf,0
	ret

;
;  Process Load Function
;
start1:
	lxi	d,8	; pt to file type
	dad	d
	mov	a,m	; get first char of file type
	cpi	' '	; any file type?
	jnz	setname	; yes, so user file given totally
	lxi	d,dirtyp	; set file type to DIR
	xchg		; copy type into TFCB
	mvi	b,3	; 3 bytes
	call	moveb
setname:
	lxi	d,tfcb	; pt to FCB
	mvi	a,80h	; only set FCB
	call	zfninit	; set new NAMES.DIR file
	call	codend	; get end of code
	call	zdname	; load NAMES.DIR file (or user file)
	jz	loaderr	; load error
	lhld	ndradr	; pt to named directory buffer
	mov	a,m	; get limit
	cmp	c	; within range?
	jnc	load1
	call	print
	db	cr,lf,'Load Error -- Not Enough Room in Memory Buffer'
	db	cr,lf,'for Directory Names -- Aborting',0
	ret
loaderr:
	call	print
	db	cr,lf,'Load Error -- File Not Found -- Aborting',0
	ret
load1:
	inx	h	; pt to dir size
	mov	m,c	; set dir size
	inx	h	; pt to first byte of first entry
	xchg		; ... in DE
	call	codend	; pt to first loaded byte in HL
load2:
	mvi	b,10	; 10 bytes/entry
load3:
	mov	a,m	; get byte
	stax	d	; put byte
	inx	h	; pt to next
	inx	d
	dcr	b	; count down
	jnz	load3
	dcr	c	; count down entries
	jnz	load2
	call	print
	db	cr,lf,'Load Complete',0
	ret

;
;  Display Contents of Loaded Directory
;
ldisp:
	lhld	ndradr	; get address
	call	print
	db	cr,lf,'**********************************************'
	db	cr,lf,'** Memory-Based Named Directory Definitions **'
	db	cr,lf,'** Number of Entries Permitted: ',0
	mov	a,m	; get count
	call	padc	; print as decimal
	call	print
	db	'         **'
	db	cr,lf,'** Number of Entries Loaded: ',0
	inx	h	; pt to count
	mov	a,m	; get count
	call	padc
	call	print
	db	'            **'
	db	cr,lf,'**********************************************',0
	ora	a	; any entries?
	jnz	ldisp0
	call	print
	db	cr,lf,'	-- No Named Directories Loaded --',0
	ret
ldisp0:
	call	print
	db	cr,lf,'	-- Named Directory Display --',0
	inx	h	; pt to first entry
	mov	b,a	; count in B
	mvi	c,0ffh	; set current disk indicator to nothing
	mvi	d,0	; set entry counter
ldisp1:
	mov	a,m	; get next disk
	cmp	c	; same as current indicator?
	jz	ldisp2	; process if same
	mov	c,a	; set new disk
	call	crlf	; new line
	adi	'A'	; convert to letter
	call	cout
	call	print
	db	' --',0
	mvi	d,0ffh	; set for increment to zero
ldisp2:
	inx	h	; pt to user number
	lda	puser	; get priv user number
	dcr	a	; back up to last non-priv number
	cmp	m	; compare to entry
	jnc	ldisp3	; go ahead and display if non-priv number
	push	b	; save BC
	lda	cuser	; get current user
	mov	b,a	; ... in B
	lda	puser	; check for privileged user
	dcr	a	; set top of non-priv users
	cmp	b	; privileged?
	pop	b	; restore BC
	jc	ldisp3	; privileged
	mov	a,l	; pt to next entry
	adi	9	; 9 bytes to next entry
	mov	l,a
	mov	a,h
	aci	0
	mov	h,a
	jmp	ldisp5
ldisp3:
	inr	d	; increment entry counter
	mov	a,d	; get count
	ani	3	; check for 4th
	cz	crlf
	mov	a,m	; get user number
	call	padc	; print user number as decimal chars
	mvi	a,':'	; print colon
	call	cout
	mvi	a,' '	; print space
	call	cout
	inx	h	; pt to first char of name
	mvi	e,8	; print 8-char name
ldisp4:
	mov	a,m	; get char of dir name
	call	cout
	inx	h	; pt to next
	dcr	e	; count down
	jnz	ldisp4
ldisp5:
	dcr	b	; count down
	jnz	ldisp1
	call	print
	db	cr,lf,cr,lf,'** Current Directory **',cr,lf,'	',0
	lhld	ndradr	; get address of buffer
	inx	h	; pt to entry count
	mov	b,m	; get entry count
	inx	h	; pt to first entry
cdisp:
	mov	c,m	; get next disk number
	inx	h	; pt to user number
	lda	cdisk	; compare to current disk
	cmp	c
	jnz	cdisp2	; skip if no match
	lda	cuser	; compare current user
	cmp	m	; to user pted to
	jnz	cdisp2	; skip if no match
	inx	h	; we have found it, so pt to first char
	lda	cdisk	; print current disk letter
	adi	'A'
	call	cout
	lda	cuser	; print current user number
	call	padc
	mvi	a,':'	; print separator
	call	cout
	mvi	a,' '
	call	cout
	mvi	b,8	; print 8 chars
cdisp1:
	mov	a,m	; get char
	call	cout	; print char
	inx	h	; pt to next
	dcr	b	; count down
	jnz	cdisp1
	ret
cdisp2:
	lxi	d,9	; skip to next entry
	dad	d
	dcr	b	; count down
	jnz	cdisp
	call	print
	db	'Not Named in Directory Buffer',0
	ret

;
;  Buffers
;
cdisk:	ds	1	; current disk number
cuser:	ds	1	; current user number
dirtyp:	db	'DIR'	; type of Directory file

	end
